﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Threading;



namespace SmartMeterParamFrame
{
    public partial class Communicate : IDisposable
    {

        private System.Threading.CancellationToken token = new System.Threading.CancellationToken(false);

        /// <summary>
        /// 身份认证类型
        /// </summary>
        public static SmartMeterParamFrame.EnumIdentityType IdentityType
        {
            get;
            set;
        }

        private EncryptionMachine em = null;

        private string meterlevel = "02";

        private string meterpwd = "000000";

        private string usercode = "00000000";
        /// <summary>
        /// 是否终止
        /// </summary>
        private bool isAbort = false;

        #region -----------------------属性---------------------------

        /// <summary>
        /// 所有连接是否准备好
        /// </summary>
        public bool IsReady
        {
            get { return IsMachineReady && IsDeviceLink; }
        }
        /// <summary>
        /// 加密机是否准备好
        /// </summary>
        public bool IsMachineReady
        {
            get;
            private set;
        }
        /// <summary>
        /// 装置驱动是否加载
        /// </summary>
        public bool IsDeviceLoading
        {
            get { return DeviceControl == null ? false : true; }
        }
        /// <summary>
        /// 装置是否联机
        /// </summary>
        public bool IsDeviceLink
        {
            get;
            private set;
        }

        /// <summary>
        /// 电能表信息对象
        /// </summary>
        public Model.MeterCollection MeterItems
        {
            get;
            private set;
        }
        /// <summary>
        /// 是否是远程费控
        /// </summary>
        public bool IsYuanCheng
        {
            private get;
            set;
        }


        /// <summary>
        /// 控制参数(写表等级|写表密码|操作者代码)
        /// </summary>
        public string ControlParam
        {
            set
            {
                if (value.Split('|').Length != 3) return;

                string[] tmp = value.Split('|');

                meterlevel = tmp[0];

                meterpwd = tmp[1];

                usercode = tmp[2];

            }
        }

        /// <summary>
        /// 设备驱动对象
        /// </summary>
        private IDevice DeviceControl
        {
            get;
            set;
        }
        /// <summary>
        /// 设置配置面板
        /// </summary>
        public IApplication setConfigPanel
        {
            set
            {
                if (DeviceControl != null)
                {
                    DeviceControl.UISet = value;
                    DeviceControl.ShowUI();
                }
            }
        }

        #endregion


        private void LoadParam()
        {
            int Bws = 0;
            if (DeviceControl == null)
            {
                Bws = 6;
            }
            else
            {
                Bws = DeviceControl.Bws;
            }

            MeterItems = new Model.MeterCollection(Bws);
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="Bws">表位数</param>
        public Communicate()
        {
            LoadDevicePlugins();
            LoadParam();
            LinkDevice();
        }

        public Communicate(string ip, string port)
            : this()
        {
            SetEncryptMachine(ip, port);
        }
        /// <summary>
        /// 重置
        /// </summary>
        public void Reset(string ip, string port)
        {
            if (em != null)
            {
                em.Dispose();
            }

            SetEncryptMachine(ip, port);

            if (DeviceControl == null)
            {
                LoadDevicePlugins();
            }

            LoadParam();

            LinkDevice();
        }

        /// <summary>
        /// 设备联机
        /// </summary>
        public void LinkDevice()
        {
            if (DeviceControl == null) return;
#if !DEBUG
            string errString;
            IsDeviceLink = DeviceControl.DeviceLink(out errString);
#else
            IsDeviceLink = true;
#endif


        }

        /// <summary>
        /// 数据清理
        /// </summary>
        public void ClearData()
        {
            MeterItems.DataClear();
        }

        /// <summary>
        /// 设置加密机参数
        /// </summary>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        public void SetEncryptMachine(string ip, string port)
        {
            em = EncryptionMachine.LinkMachine(ip, port, "1000");
            IsMachineReady = em == null ? false : true;
            //IsMachineReady = false;
            //em.Dispose();
        }
        /// <summary>
        /// 设置装置表位数
        /// </summary>
        public void SetBwCount(int Bws)
        {
            MeterItems.Clear();

            MeterItems = new Model.MeterCollection(Bws);
        }

        ///// <summary>
        ///// 在配置完毕后重新加载表位数
        ///// </summary>
        //public void ReLoadBws()
        //{
        //    int Bws = 0;
        //    if (DeviceControl==null)
        //    {
        //        Bws = 6;
        //    }
        //    else
        //    {
        //        Bws = DeviceControl.Bws;
        //    }
        //    MeterItems = new Model.MeterCollection(Bws);
        //}

        /// <summary>
        /// 开始方案项目操作
        /// </summary>
        /// <param name="faList">方案列表对象</param>
        /// <param name="U">升源电压</param>
        /// <param name="CallBackFinish">方案操作结束回调</param>
        /// <param name="CallBackFaListMove">项目列表UI移动回调</param>
        /// <param name="CallBackKeyDownMessage">密钥下装插卡提示回调</param>
        public void StarWork(Model.FACollection faList, float U, Action<string, bool> ShowPowerWaiting, Action CallBackFinish, Action<int> CallBackFaListMove = null, Func<string, bool> CallBackKeyDownMessage = null)
        {

#if !DEBUG
            string errString;
            if (!this.DeviceControl.PowerOn(U, out errString))
            {
                if (this.DeviceControl.DeviceLink(out errString) == false || this.DeviceControl.PowerOn(U, out errString) == false)
                {
                    System.Windows.MessageBox.Show("升源失败：\r\n1:您可以重新操作\r\n2:关闭软件软件后，关闭台体，然后开启台体后再启动软件", "操作警告", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
                    CallBackFinish();
                    return;
                }
            }
#endif
            if (ShowPowerWaiting != null)
            {
                for (int i = 800; i > 0; i--)
                {
                    ShowPowerWaiting(string.Format("正在等待源稳定({0})", i), false);
                    System.Threading.Thread.Sleep(10);
                    ApplocationDoEvents.DoEvents();
                }
                ShowPowerWaiting("", true);
            }

            System.Threading.Tasks.Task.Factory.StartNew(new Action(() => Working(faList, CallBackFinish, CallBackFaListMove, CallBackKeyDownMessage)));

        }

        /// <summary>
        /// 终止操作
        /// </summary>
        public void Abort()
        {
            isAbort = true;

            //while (isAbort)
            //{
            //    ApplocationDoEvents.DoEvents();
            //}
            //PowerOff();
        }

        /// <summary>
        /// 关闭源控
        /// </summary>
        private void PowerOff()
        {
#if !DEBUG
            string errString;
            if (IsDeviceLink)
                if (!DeviceControl.PowerOff(out errString))
                {
                    throw new Exception(errString);
                }
#endif
        }

        /// <summary>
        /// 开始操作
        /// </summary>
        /// <param name="faList"></param>
        /// <param name="CallBackFinish"></param>
        /// <param name="CallBackFaListMove"></param>
        /// <param name="CallBackKeyDownMessage"></param>
        private void Working(Model.FACollection faList, Action CallBackFinish, Action<int> CallBackFaListMove = null, Func<string, bool> CallBackKeyDownMessage = null)
        {
            this.InitThreadInfo();

            for (int i = 0; i < faList.Count; i++)
            {
                if (isAbort == false)
                {
                    if (faList[i].PrjType == EnumFAType.费控功能 || faList[i].PrjType == EnumFAType.密钥下装)
                    {
                        if (!IsMachineReady) continue;
                    }

                    if (!MeterItems.IsFaYaoJian(faList[i].PrjOrderID)) continue;

                    if (CallBackFaListMove != null)
                    {
                        CallBackFaListMove(i);
                    }

                    MeterItems.ResetCurrentProjectMsg(faList[i].PrjOrderID);

                    for (int j = 0; j < MeterItems.Count; j++)
                    {
                        if (!MeterItems[j].CheckYn || (MeterItems[j].IsFailed && MeterItems[j].getPrjResult(faList[i].PrjOrderID, true) != EnumResult.失败)) continue;
                    }

                    this.Star(faList[i], CallBackKeyDownMessage);
                }
                else
                {
                    break;
                }
            }
            isAbort = false;
            CallBackFinish();   //回调完成函数
            try
            {
                PowerOff();
            }
            catch (Exception ex)
            {
                System.Windows.MessageBox.Show(ex.Message, "关源失败", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
            }
        }


        /// <summary>
        /// 加载驱动插件
        /// </summary>
        /// <returns></returns>
        private bool LoadDevicePlugins()
        {
            string path = System.Environment.CurrentDirectory + @"\Plugins";
            try
            {
                var items = from i in System.IO.Directory.GetFiles(path)
                            where System.IO.File.Exists(i) && (new System.IO.FileInfo(i)).Extension.ToLower() == ".dll"
                            select i;

                foreach (string s in items)
                {
                    System.Reflection.Assembly asb = null;

                    try
                    {
                        asb = System.Reflection.Assembly.LoadFile(s);
                    }
                    catch { continue; }

                    try
                    {
                        IDevice device = (from t in asb.GetTypes()
                                          where t.GetInterface("IDevice") != null
                                          select (IDevice)Activator.CreateInstance(t)).First();
                        DeviceControl = device;
                        return true;
                    }
                    catch { return false; }
                }
            }
            catch { }
            return false;
        }



        #region IDisposable 成员

        public void Dispose()
        {
            try
            {
#if !DEBUG
                string errString;
                if (IsMachineReady) em.Dispose();
                if (IsDeviceLink) DeviceControl.DeviceOffLink(out errString);
#endif
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        #endregion
    }
}
